#include "header.h"

extern game world;
battle::battle(){} //NEVER USE ME, IT WON'T WORK
battle::battle(character &player, vector<monster> &monsters) //USE ME
{
  toBattleAnimation();
  inBattle = true;
  int selectedMonster=-1;
  int selectedAttackGem=-1;
  int selectedDefenseGem=-1;
  //init above this
  cout << "Battle Start!";
  getch();
  
  //main code here
  while (inBattle)
  {
    selectedMonster = selectMonsterMenu(player,monsters);
    selectedAttackGem = selectAttackGemBattleMenu(player);
    selectedDefenseGem = selectDefenseGemBattleMenu(player,selectedAttackGem);
    
    playerAttack(player,monsters,selectedMonster,selectedAttackGem);
    monsterAttack(player,monsters,selectedDefenseGem);
    checkState(player,monsters,inBattle);
    getch();
  }
  
  //deinit below this
  world.maps[world.currentboard].updateRect(room(0,0,80,25));
  delete world.cbattle;
  
}

int battle::selectMonsterMenu(character &player, vector<monster> monsters)
{
  cout << Color(white, black) << Clear();
  int count=97;
  cout << "Your HP: " << player.hp << "/" << player.maxhp << endl;
  for (vector<monster>::const_iterator monIterate = monsters.begin(); monIterate < monsters.end(); monIterate++)
  {
    cout << static_cast<char>(count) << ": " << monIterate->name << " HP: " << monIterate->hp << "/" << monIterate->maxhp << endl;
    count++;
  }
  cout << "Select your target" << endl;
  char in = getBattleMenuInput(count); // passes in count so I know how many letters to accept
  return static_cast<int>(in)-97;
}

int battle::selectAttackGemBattleMenu(character &player)
{
  cout << Color(white, black) << Clear();
  int count = 97;
  for (int counter=97;counter<117;counter++)
  {
    if (player.inventory[counter-97].name!="Empty")
    {
      cout << static_cast<char>(counter) << ": " << player.inventory[counter-97].name << endl;
      count++;
    }
  }
  cout << "Select your attack gem" << endl;
  char in = getAttackGemMenuInput(count);
  return static_cast<int>(in)-97;
}

int battle::selectDefenseGemBattleMenu(character &player, int agem)
{
  cout << Color(white, black) << Clear();
  int count = 97;
  for (int counter=97;counter<117;counter++)
  {
    if (player.inventory[counter-97].name!="Empty" && counter-97!=agem)
    {
      cout << static_cast<char>(counter) << ": " << player.inventory[counter-97].name << endl;
      count++;
    }
  }
  cout << "Select your defense gem" << endl;
  char in = getDefenseGemMenuInput(count, agem);
  return static_cast<int>(in)-97;
}

char battle::getBattleMenuInput(int n)
{
  char input = getch();
  while (static_cast<int>(input)<97 || static_cast<int>(input)>=n)
  {
    input = getch();
  }
  return input;
}

char battle::getAttackGemMenuInput(int n)
{
  char input = getch();
  while (static_cast<int>(input)<97 || static_cast<int>(input)>=n)
  {
    input = getch();
  }
  return input;
}

char battle::getDefenseGemMenuInput(int n, int agem)
{
  char input = getch();
  while (static_cast<int>(input)<97 || static_cast<int>(input)>=n+1 || static_cast<int>(input)==97+agem)
  {
    input = getch();
  }
  return input;
}

void battle::playerAttack(character &player, vector<monster> &monsters, int selectedMonster, int selectedAGem)
{
  int playerPower = player.inventory[selectedAGem].power;
  gemElement playerAttackElement = player.inventory[selectedAGem].element;
  gemType playerAttackType = player.inventory[selectedAGem].type;
  
  int monsterDefense = monsters.at(selectedMonster).power;
  double monsterDamageFactor = monsters.at(selectedMonster).resistFactor(playerAttackElement,playerAttackType);
  
  int damage = computeDamage(playerPower,monsterDamageFactor,monsterDefense);
  if (damage<0) damage=0;
  cout << "You dealt " << damage << " points of damage!" << endl;
  monsters.at(selectedMonster).hp-=damage;
  
  checkGemBreak(selectedAGem);
}

void battle::monsterAttack(character &player, vector<monster> &monsters, int selectedDGem)
{
  
  int playerDefense = player.inventory[selectedDGem].defense;
  gemElement playerDefenseElement = player.inventory[selectedDGem].element;
  
  for (vector<monster>::const_iterator monIterate = monsters.begin();monIterate!=monsters.end();monIterate++)
  {
    int damage = computeDamage(monIterate->power,player.resistFactor(monIterate->element,playerDefenseElement),playerDefense);
    if (damage<0) damage = 0;
    cout << "The " << monIterate->name << " did " << damage << " damage to you!" << endl;
    player.hp-=damage;
    if(damage>0) checkGemBreak(selectedDGem);
  }
}

void battle::checkState(character &player, vector<monster> &monsters, bool &inBattle)
{
  if (player.hp<=0)
  {
    cout << "You have died!";
    inBattle = false;
    world.playing = false;
  }
  bool allMonsDead = true;
  for (vector<monster>::iterator monsIterate=monsters.begin();monsIterate!=monsters.end();monsIterate++)
  {
    if (monsIterate->hp>0)
    {
      allMonsDead = false;
    }
    else
    {
      monsters.erase(monsIterate);
      monsIterate--;
    }
  }
  
  if (allMonsDead)
  {
    inBattle = false;
    battleWin(player,monsters);
  }
}

void battle::checkGemBreak(int gemNum)
{
  world.player.inventory[gemNum].currentDurability--;
  if (world.player.inventory[gemNum].currentDurability<=0) 
  {
    breakGem(world.player.inventory[gemNum]);
    //Put code to rearrange gems here to keep them consecutive.
    arrangePlayerGems();
  }
  
}

int battle::computeDamage(int attack, double resistFactor, int defense)
{
  return int(ceil( ( pow(attack,3/2) * resistFactor ) - pow(defense,3/2) ) );
}

void battle::battleWin(character &player, vector<monster> &monsters)
{
  cout << "You win!" << endl;
  
}



void battle::toBattleAnimation()
{
  for (int n=0;n<3;n++)
  {
    cout << Color(red, red);
    for (int y=0;y<25;y++)
    {
      Sleep(1);
      for (int x=0;x<80;x++)
      {
        cout << gotoxy(x,y) << " ";
      }
    }
    cout << Color(lightred, lightred);
    for (int y=0;y<25;y++)
    {
      Sleep(1);
      for (int x=0;x<80;x++)
      {
        cout << gotoxy(x,y) << " ";
      }
    }
    cout << Color(red, red);
    for (int y=0;y<25;y++)
    {
      Sleep(1);
      for (int x=0;x<80;x++)
      {
        cout << gotoxy(x,y) << " ";
      } //end x
    }// end y
  }// end n
}
